package com.caigua.mgp.mg.internal;

import com.caigua.mgp.mg.codegen.customize.rules.CustomizeConditionalModelRules;
import com.caigua.mgp.mg.codegen.customize.javamapper.CustomizeJavaMapperGenerator;
import com.caigua.mgp.mg.utils.GenUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.CaseUtils;
import org.mybatis.generator.api.ProgressCallback;
import org.mybatis.generator.codegen.AbstractJavaClientGenerator;
import org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3Impl;
import org.mybatis.generator.codegen.mybatis3.javamapper.AnnotatedClientGenerator;
import org.mybatis.generator.codegen.mybatis3.javamapper.JavaMapperGenerator;
import org.mybatis.generator.codegen.mybatis3.javamapper.MixedClientGenerator;
import org.mybatis.generator.config.ModelType;
import org.mybatis.generator.internal.ObjectFactory;
import org.mybatis.generator.internal.rules.FlatModelRules;
import org.mybatis.generator.internal.rules.HierarchicalModelRules;

import java.util.EnumMap;
import java.util.List;
import java.util.Map;

/**
 * @BelongsProject: mybatis_generator_pluing
 * @BelongsPackage: com.caigua.mgp.mg.internal
 * @Author: caigua
 * @CreateTime: 2020-12-09 12:56
 * @Description: todo
 */
public class CustomizeIntrospectedTableMyBatis3Impl extends IntrospectedTableMyBatis3Impl {

    protected enum InternalAttribute {
        ATTR_QUERY_PAGE,
        ATTR_LIST_PAGE_FILTER,
        ATTR_LIST_PAGE_SORT,
        ATTR_QUERY_BY_IDS;
    }


    /** Internal attributes are used to store commonly accessed items by all code generators. */
    protected Map<InternalAttribute, String> internalAttributes =
            new EnumMap<>(InternalAttribute.class);


    @Override
    public void initialize() {
        calculateJavaClientAttributes();
        calculateModelAttributes();
        calculateXmlAttributes();

        if (tableConfiguration.getModelType() == ModelType.HIERARCHICAL) {
            rules = new HierarchicalModelRules(this);
        } else if (tableConfiguration.getModelType() == ModelType.FLAT) {
            rules = new FlatModelRules(this);
        } else {
            rules = new CustomizeConditionalModelRules(this);
        }

        context.getPlugins().initialized(this);
    }

    @Override
    protected String calculateMyBatis3XmlMapperFileName() {
        StringBuilder sb = new StringBuilder();
        if(StringUtils.isNotBlank(GenUtil.domainOverPrefix.toString())) {
            sb.append(CaseUtils.toCamelCase(fullyQualifiedTable.getIntrospectedTableName().substring(GenUtil.domainOverPrefix.toString().length()) ,  true, new char[]{'_'}));
        }else {
            sb.append(CaseUtils.toCamelCase(fullyQualifiedTable.getIntrospectedTableName() ,  true, new char[]{'_'}));
        }
        sb.append("Mapper.xml"); //$NON-NLS-1$
        return sb.toString();
    }

    @Override
    protected void calculateJavaClientAttributes() {
        if (context.getJavaClientGeneratorConfiguration() == null) {
            return;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(calculateJavaClientImplementationPackage());
        sb.append('.');
        sb.append(fullyQualifiedTable.getDomainObjectName());
        sb.append("DAOImpl"); //$NON-NLS-1$
        setDAOImplementationType(sb.toString());

        sb.setLength(0);
        sb.append(calculateJavaClientInterfacePackage());
        sb.append('.');
        sb.append(fullyQualifiedTable.getDomainObjectName());
        sb.append("DAO"); //$NON-NLS-1$
        setDAOInterfaceType(sb.toString());

        sb.setLength(0);
        sb.append(calculateJavaClientInterfacePackage());
        sb.append('.');

        if(StringUtils.isNotBlank(GenUtil.domainOverPrefix.toString())) {
            sb.append(CaseUtils.toCamelCase(fullyQualifiedTable.getIntrospectedTableName().substring(GenUtil.domainOverPrefix.toString().length()) ,  true, new char[]{'_'}));
        }else {
            sb.append(CaseUtils.toCamelCase(fullyQualifiedTable.getIntrospectedTableName() ,  true, new char[]{'_'}));
        }
//        sb.append(fullyQualifiedTable.getIntrospectedTableName());
        sb.append("Mapper"); //$NON-NLS-1$
        setMyBatis3JavaMapperType(sb.toString());

        sb.setLength(0);
        sb.append(calculateJavaClientInterfacePackage());
        sb.append('.');
        sb.append(fullyQualifiedTable.getDomainObjectName());
        sb.append("SqlProvider"); //$NON-NLS-1$
        setMyBatis3SqlProviderType(sb.toString());
    }

    @Override
    protected AbstractJavaClientGenerator createJavaClientGenerator() {

        if (context.getJavaClientGeneratorConfiguration() == null) {
            return null;
        }

        String type = context.getJavaClientGeneratorConfiguration()
                .getConfigurationType();

        AbstractJavaClientGenerator javaGenerator;
        if ("XMLMAPPER".equalsIgnoreCase(type)) { //$NON-NLS-1$
            javaGenerator = new JavaMapperGenerator();
        } else if ("MIXEDMAPPER".equalsIgnoreCase(type)) { //$NON-NLS-1$
            javaGenerator = new MixedClientGenerator();
        } else if ("ANNOTATEDMAPPER".equalsIgnoreCase(type)) { //$NON-NLS-1$
            javaGenerator = new AnnotatedClientGenerator();
        } else if ("MAPPER".equalsIgnoreCase(type)) { //$NON-NLS-1$
            javaGenerator = new JavaMapperGenerator();
        }else if ("CUSTOMIZE".equalsIgnoreCase(type)) {
            javaGenerator = new CustomizeJavaMapperGenerator();
        } else {
            javaGenerator = (AbstractJavaClientGenerator) ObjectFactory
                    .createInternalObject(type);
        }

        return javaGenerator;

    }



    @Override
    protected void calculateXmlMapperGenerator(AbstractJavaClientGenerator javaClientGenerator, List<String> warnings, ProgressCallback progressCallback) {
        super.calculateXmlMapperGenerator(javaClientGenerator, warnings, progressCallback);
    }

    @Override
    protected void calculateXmlAttributes() {
        super.calculateXmlAttributes();
        setMyBatis3XmlMapperFileName(calculateMyBatis3XmlMapperFileName());
        this.setDeleteByPrimaryKeyStatementId("delete");
        this.setSelectByPrimaryKeyStatementId("get");
        this.setUpdateByPrimaryKeySelectiveStatementId("update");
        this.setInsertSelectiveStatementId("insert");
        this.setQueryPage("queryPage");
        this.setQueryByIds("queryByIds");
        this.setSelectAllStatementId("selectAll");
        this.setBaseResultMapId("BaseResultMap");
        this.setBaseColumnListId("Base_Column_List");
        this.setListPageFilterId("listPageFilter");
        this.setListPageSortId("listPageSort");
    }



    public String getQueryPage() {
        return (String)this.internalAttributes.get(InternalAttribute.ATTR_QUERY_PAGE);
    }

    public void setQueryPage(String s) {
        this.internalAttributes.put(InternalAttribute.ATTR_QUERY_PAGE, s);
    }

    public String getQueryByIds() {
        return (String)this.internalAttributes.get(InternalAttribute.ATTR_QUERY_BY_IDS);
    }

    public void setQueryByIds(String s) {
        this.internalAttributes.put(InternalAttribute.ATTR_QUERY_BY_IDS, s);
    }

    public void setListPageFilterId(String s) {
        this.internalAttributes.put(InternalAttribute.ATTR_LIST_PAGE_FILTER, s);
    }

    public void setListPageSortId(String s) {
        this.internalAttributes.put(InternalAttribute.ATTR_LIST_PAGE_SORT, s);
    }

    public String getListPageFilterId() {
        return (String)this.internalAttributes.get(InternalAttribute.ATTR_LIST_PAGE_FILTER);
    }

    public String getListPageSortId() {
        return (String)this.internalAttributes.get(InternalAttribute.ATTR_LIST_PAGE_SORT);
    }
}
